#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
XGO机械狗LED控制接口
基于串口协议开发的LED控制函数
"""

from xgolib import XGO
import time

class XGO_LED_Controller:
    def __init__(self, dog_instance):
        """
        初始化LED控制器
        :param dog_instance: XGO实例对象
        """
        self.dog = dog_instance
        # LED地址定义
        self.LED_ADDRESSES = {
            1: 0x69,  # 1号LED地址
            2: 0x6A,  # 2号LED地址  
            3: 0x6B   # 3号LED地址
        }
    
    def _calculate_checksum(self, data_bytes):
        """
        计算校验和
        :param data_bytes: 数据字节列表
        :return: 校验和
        """
        checksum = sum(data_bytes) & 0xFF  # 取最低字节
        return (~checksum) & 0xFF  # 取反
    
    def _send_led_command(self, led_id, r, g, b, method='auto'):
        """
        发送LED控制命令
        :param led_id: LED编号 (1-3)
        :param r: 红色分量 (0-255)
        :param g: 绿色分量 (0-255)
        :param b: 蓝色分量 (0-255)
        :param method: 发送方法 ('auto', 'private', 'direct', 'builtin')
        """
        if led_id not in self.LED_ADDRESSES:
            raise ValueError("LED编号必须在1-3之间")
        
        # 限制RGB值范围
        r = max(0, min(255, int(r)))
        g = max(0, min(255, int(g)))
        b = max(0, min(255, int(b)))
        
        address = self.LED_ADDRESSES[led_id]
        
        # 方法1: 检查是否有内置的LED控制方法
        if method == 'builtin' or (method == 'auto' and hasattr(self.dog, 'set_led')):
            try:
                # 尝试使用可能存在的内置LED方法
                if hasattr(self.dog, 'set_led'):
                    self.dog.set_led(led_id, r, g, b)
                    return
                elif hasattr(self.dog, 'led_color'):
                    self.dog.led_color(led_id, r, g, b)
                    return
            except Exception as e:
                print(f"内置LED方法失败，尝试其他方法: {e}")
        
        # 构建数据帧
        frame_header = [0x55, 0x00]  # 帧头
        frame_length = 0x0B  # 帧长度 (固定11字节)
        command_type = 0x00  # 写指令
        
        # 数据部分：地址 + RGB三个字节
        data = [address, r, g, b]
        
        # 计算校验和
        checksum_data = [frame_length, command_type] + data
        checksum = self._calculate_checksum(checksum_data)
        
        frame_tail = [0x00, 0xAA]  # 帧尾
        
        # 完整数据帧
        full_frame = frame_header + [frame_length, command_type] + data + [checksum] + frame_tail
        
        # 方法2: 使用私有方法 (推荐)
        if method == 'private' or method == 'auto':
            try:
                # 使用私有方法__send发送完整数据帧
                self.dog._XGO__send(bytes(full_frame))
                return
            except Exception as e:
                print(f"私有方法发送失败: {e}")
                if method == 'private':
                    raise
        
        # 方法3: 直接使用串口对象
        if method == 'direct' or method == 'auto':
            try:
                if hasattr(self.dog, 'ser') and hasattr(self.dog.ser, 'write'):
                    self.dog.ser.write(bytes(full_frame))
                    return
            except Exception as e:
                print(f"直接串口发送失败: {e}")
                if method == 'direct':
                    raise
        
        # 如果所有方法都失败
        print(f"⚠️ 所有发送方法都失败了")
        print(f"数据帧: {[hex(b) for b in full_frame]}")
        raise Exception("无法发送LED命令")
    
    def set_led_color(self, led_id, r, g, b, method='auto'):
        """
        设置单个LED颜色
        :param led_id: LED编号 (1-3)
        :param r: 红色分量 (0-255)
        :param g: 绿色分量 (0-255)
        :param b: 蓝色分量 (0-255)
        :param method: 发送方法 ('auto', 'private', 'direct', 'builtin')
        """
        self._send_led_command(led_id, r, g, b, method)
        print(f"设置LED{led_id}颜色: R={r}, G={g}, B={b}")
    
    def set_all_leds_color(self, r, g, b, method='auto'):
        """
        设置所有LED为相同颜色
        :param r: 红色分量 (0-255)
        :param g: 绿色分量 (0-255)
        :param b: 蓝色分量 (0-255)
        :param method: 发送方法 ('auto', 'private', 'direct', 'builtin')
        """
        for led_id in range(1, 4):
            self._send_led_command(led_id, r, g, b, method)
            time.sleep(0.001)  # 间隔1ms避免指令过快
        print(f"设置所有LED颜色: R={r}, G={g}, B={b}")
    
    def get_connection_info(self):
        """
        获取连接信息和可用的串口方法
        """
        print("🔍 XGO连接信息:")
        print("-" * 30)
        
        # 检查串口对象
        if hasattr(self.dog, 'ser'):
            print(f"✓ 串口对象: {type(self.dog.ser)}")
            if hasattr(self.dog.ser, 'port'):
                print(f"  端口: {self.dog.ser.port}")
            if hasattr(self.dog.ser, 'baudrate'):
                print(f"  波特率: {self.dog.ser.baudrate}")
            if hasattr(self.dog.ser, 'is_open'):
                print(f"  连接状态: {'已连接' if self.dog.ser.is_open else '未连接'}")
        
        # 检查可用方法
        methods = []
        if hasattr(self.dog, '_XGO__send'):
            methods.append('private (推荐)')
        if hasattr(self.dog, 'ser') and hasattr(self.dog.ser, 'write'):
            methods.append('direct')
        if hasattr(self.dog, 'set_led') or hasattr(self.dog, 'led_color'):
            methods.append('builtin')
        
        print(f"✓ 可用通信方法: {', '.join(methods)}")
        
        # 读取基本信息
        try:
            version = self.dog.read_firmware()
            print(f"✓ 固件版本: {version}")
        except:
            print("✗ 无法读取固件版本")
        
        try:
            battery = self.dog.read_battery()
            print(f"✓ 电池电量: {battery}%")
        except:
            print("✗ 无法读取电池电量")
    
    def test_communication(self):
        """
        测试不同的通信方法
        """
        print("🧪 测试LED通信方法:")
        print("-" * 30)
        
        methods = ['builtin', 'private', 'direct']
        test_colors = [(255, 0, 0), (0, 255, 0), (0, 0, 255)]  # 红绿蓝
        
        for i, method in enumerate(methods):
            print(f"\n测试方法 {i+1}: {method}")
            try:
                r, g, b = test_colors[i % len(test_colors)]
                self.set_led_color(1, r, g, b, method=method)
                print(f"  ✓ {method} 方法成功")
                time.sleep(1)
                self.turn_off_led(1)  # 关闭LED
                time.sleep(0.5)
            except Exception as e:
                print(f"  ✗ {method} 方法失败: {e}")
        
        print("\n测试完成！")
    
    def turn_off_led(self, led_id):
        """
        关闭指定LED
        :param led_id: LED编号 (1-3)
        """
        self.set_led_color(led_id, 0, 0, 0)
    
    def turn_off_all_leds(self):
        """
        关闭所有LED
        """
        self.set_all_leds_color(0, 0, 0)
    
    def set_led_white(self, led_id, brightness=255):
        """
        设置LED为白色
        :param led_id: LED编号 (1-3)
        :param brightness: 亮度 (0-255)
        """
        self.set_led_color(led_id, brightness, brightness, brightness)
    
    def set_led_red(self, led_id, brightness=255):
        """
        设置LED为红色
        :param led_id: LED编号 (1-3)
        :param brightness: 亮度 (0-255)
        """
        self.set_led_color(led_id, brightness, 0, 0)
    
    def set_led_green(self, led_id, brightness=255):
        """
        设置LED为绿色
        :param led_id: LED编号 (1-3)
        :param brightness: 亮度 (0-255)
        """
        self.set_led_color(led_id, 0, brightness, 0)
    
    def set_led_blue(self, led_id, brightness=255):
        """
        设置LED为蓝色
        :param led_id: LED编号 (1-3)
        :param brightness: 亮度 (0-255)
        """
        self.set_led_color(led_id, 0, 0, brightness)
    
    def led_rainbow_cycle(self, duration=5):
        """
        LED彩虹循环效果
        :param duration: 循环持续时间(秒)
        """
        import math
        
        start_time = time.time()
        while time.time() - start_time < duration:
            # 使用正弦波生成彩虹色
            t = time.time() - start_time
            for led_id in range(1, 4):
                phase = (led_id - 1) * 2 * math.pi / 3  # 每个LED相位差120度
                r = int(128 + 127 * math.sin(2 * math.pi * t / 2 + phase))
                g = int(128 + 127 * math.sin(2 * math.pi * t / 2 + phase + 2 * math.pi / 3))
                b = int(128 + 127 * math.sin(2 * math.pi * t / 2 + phase + 4 * math.pi / 3))
                self.set_led_color(led_id, r, g, b)
                time.sleep(0.001)
            time.sleep(0.05)  # 控制更新频率


# 使用示例和测试函数
def main():
    """
    主函数 - 初始化和使用示例
    """
    # 初始化XGO机械狗
    from xgolib import XGO
    dog = XGO("xgolite")
    
    # 判断狗的类型
    version = dog.read_firmware()
    if version[0] == 'M':
        print('XGO-MINI')
        dog = XGO("xgomini")
        dog_type = 'M'
    else:
        print('XGO-LITE')
        dog_type = 'L'
    
    # 初始化LED控制器
    led_controller = XGO_LED_Controller(dog)
    
    print("开始LED测试...")
    
    try:
        # 显示连接信息
        print("🔍 检查XGO连接状态...")
        led_controller.get_connection_info()
        
        # 测试不同的通信方法
        print("\n🧪 测试LED通信方法...")
        led_controller.test_communication()
        
        print("\n🎨 开始LED演示...")
        
        # 测试1: 单独控制每个LED
        print("测试1: 单独控制每个LED")
        led_controller.set_led_red(1)      # LED1红色
        time.sleep(1)
        led_controller.set_led_green(2)    # LED2绿色
        time.sleep(1)
        led_controller.set_led_blue(3)     # LED3蓝色
        time.sleep(1)
        
        # 测试2: 所有LED设为白色
        print("测试2: 所有LED设为白色")
        led_controller.set_all_leds_color(255, 255, 255)
        time.sleep(2)
        
        # 测试3: 关闭所有LED
        print("测试3: 关闭所有LED")
        led_controller.turn_off_all_leds()
        time.sleep(1)
        
        # 测试4: 彩虹循环效果
        print("测试4: 彩虹循环效果")
        led_controller.led_rainbow_cycle(5)
        
        # 测试5: 使用不同的通信方法
        print("测试5: 测试不同通信方法")
        methods = ['auto', 'private', 'direct']
        colors = [(255, 100, 0), (100, 255, 0), (0, 100, 255)]
        
        for method, color in zip(methods, colors):
            print(f"  使用 {method} 方法...")
            try:
                led_controller.set_all_leds_color(color[0], color[1], color[2], method=method)
                time.sleep(1.5)
            except Exception as e:
                print(f"  {method} 方法失败: {e}")
        
        # 最后关闭所有LED
        led_controller.turn_off_all_leds()
        print("✅ LED测试完成!")
        
    except KeyboardInterrupt:
        print("\n⚠️ 测试被中断")
        led_controller.turn_off_all_leds()
    except Exception as e:
        print(f"❌ 测试过程中出现错误: {e}")
        led_controller.turn_off_all_leds()


if __name__ == "__main__":
    main()